package com.topc.participant.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.topc.base.constant.RedisConstant;
import com.topc.base.exception.Asserts;
import com.topc.core.sevice.RedisService;
import com.topc.participant.mapper.AdminInfoMapper;
import com.topc.participant.mapper.RoleInfoMapper;
import com.topc.participant.mapper.RoleMenuMidMapper;
import com.topc.participant.model.dto.SaveAdminDto;
import com.topc.participant.model.dto.UpdatePasswordDto;
import com.topc.participant.model.po.AdminInfo;
import com.topc.participant.model.po.RoleInfo;
import com.topc.participant.model.vo.AdminDetailVo;
import com.topc.participant.model.vo.AdminProjectDynamicVo;
import com.topc.participant.model.vo.AdminShowVo;
import com.topc.participant.service.IAdminInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.topc.participant.service.IEmailService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;


import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 管理员信息表 服务实现类
 * </p>
 *
 * @author Gogoing
 */
@Slf4j
@Service
public class AdminInfoServiceImpl extends ServiceImpl<AdminInfoMapper, AdminInfo> implements IAdminInfoService {

    @Autowired
    private RedisService redisService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private RoleInfoMapper roleInfoMapper;

    @Autowired
    private RoleMenuMidMapper roleMenuMidMapper;

    @Autowired
    private IEmailService emailService;

    @Override
    public void logout(String number) {
        redisService.del(RedisConstant.ADMIN_ONLINE_NUMBER+number);
    }

    @Override
    public AdminDetailVo getAdminInfoByNumber(String number) {
        AdminInfo adminInfo = this.getBaseMapper().getAdminInfoByNumber(number).setPassword(null);
        AdminDetailVo adminDetailVO = new AdminDetailVo();
        BeanUtil.copyProperties(adminInfo,adminDetailVO);
        RoleInfo roleInfo = roleInfoMapper.selectById(adminInfo.getRoleId());
        String[] menuCodeByRoleId = roleMenuMidMapper.getMenuCodeByRoleId(roleInfo.getId());
        adminDetailVO.setMenuList(menuCodeByRoleId).setRoleCode(roleInfo.getRoleCode()).setRoleName(roleInfo.getRoleName());
        return adminDetailVO;
    }

    @Override
    public String setAdminAvatar(String newPath, String number) {
        AdminInfo adminInfoByNumber = this.getBaseMapper().getAdminInfoByNumber(number);
        if (ObjectUtil.isEmpty(adminInfoByNumber)) Asserts.fail("账号不存在");
        LambdaUpdateWrapper<AdminInfo> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(AdminInfo::getAvatarUrl,newPath).eq(AdminInfo::getNumber,number);
        boolean update = this.update(lambdaUpdateWrapper);
        if (!update) Asserts.fail("路径更新失败");
        return adminInfoByNumber.getAvatarUrl();
    }

    @Override
    public void updatePassword(UpdatePasswordDto passwordDto,String number) {
        AdminInfo adminInfo = this.getBaseMapper().getAdminInfoByNumber(number);
        boolean matches = passwordEncoder.matches(passwordDto.getOldPassword(), adminInfo.getPassword());
        if (!matches) Asserts.fail("密码输入有误");
        LambdaUpdateWrapper<AdminInfo> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(AdminInfo::getPassword,passwordEncoder.encode(passwordDto.getNewPassword()))
                .eq(AdminInfo::getNumber,number);
        boolean update = this.update(lambdaUpdateWrapper);
        if (!update) Asserts.fail("修改失败");
    }

    @Override
    public List<AdminShowVo> showAdminTeam() {
        List<AdminShowVo> adminTeamVos = this.getBaseMapper().getAdminTeamList();
        return adminTeamVos;
    }

    @Override
    public List<AdminProjectDynamicVo> getProjectDynamic() {
        Map<String, AdminShowVo> sourceCollect = this.showAdminTeam().stream().collect(Collectors.toMap(
                AdminShowVo::getNumber,
                obj -> obj,
                (key1, key2) -> key1
        ));
        List<Object> dynamicStrings = redisService.lRange(RedisConstant.ADMIN_PROJECT_DYNAMIC_EVALUATION,0, redisService.lSize(RedisConstant.ADMIN_PROJECT_DYNAMIC_EVALUATION));
        List<AdminProjectDynamicVo> targetCollect = dynamicStrings.stream().map(obj -> {
            String s = (String) obj;
            String number = s.split(":")[0];
            AdminProjectDynamicVo adminProjectDynamicVo = new AdminProjectDynamicVo();
            BeanUtil.copyProperties(sourceCollect.get(number), adminProjectDynamicVo);
            return adminProjectDynamicVo.setContext(s);
        }).collect(Collectors.toList());
        return targetCollect;
    }

    @Override
    public Boolean isHasRoleInAdmin(Long roleId) {
        LambdaQueryWrapper<AdminInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AdminInfo::getRoleId,roleId);
        int count = this.count(queryWrapper);
        return count>0;
    }

    @Override
    public Long saveAdminInfo(SaveAdminDto saveAdminDto) {
        AdminInfo adminInfo = new AdminInfo();
        BeanUtil.copyProperties(saveAdminDto, adminInfo);
        String password = RandomUtil.randomString(8);
        adminInfo.setPassword(passwordEncoder.encode(password));
        boolean save = this.save(adminInfo);
        if (!save) Asserts.fail("保存失败");
        emailService.sendPassword("admin",saveAdminDto.getEmail(),password,saveAdminDto.getUsername());
        return adminInfo.getId();
    }

    @Override
    public void updateAdminInfo(SaveAdminDto saveAdminDto) {
        LambdaUpdateWrapper<AdminInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(AdminInfo::getRoleId,saveAdminDto.getRoleId())
                .set(AdminInfo::getUsername,saveAdminDto.getUsername())
                .set(AdminInfo::getStatus,saveAdminDto.getStatus());
        updateWrapper.eq(AdminInfo::getNumber,saveAdminDto.getNumber());
        boolean update = this.update(updateWrapper);
        if (!update) Asserts.fail("更新失败");

    }


}
